<template>
  <div style="padding: 10px">
    <p style="
        position: absolute;
        padding: 0;
        right: 0;
        margin-right: 10px;
        margin-top: 0px;
        text-align: center;
        z-index: 999;
      ">
      <el-button type="danger" @click="closeConnect">关闭连接</el-button>
    </p>
    <div style="margin-right: 0px; padding: 40px; background: black">

      <div id="terminal" v-loading="loading" :element-loading-text="loadingText" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)" />

    </div>

  </div>
</template>

<script>

import { Terminal } from "xterm";
import "xterm/lib/xterm.js";
import "xterm/css/xterm.css";
import Cookies from 'js-cookie'
export default {
  name: "WSTernimal",
  data () {
    return {
      term: null,
      terminalSocket: null,
      id: window.hostid,
      loading: true,
      loadingText: "开始创建Terminal......",
      cols: "",
      rows: "",
    };
  },
  created() {
    window.addEventListener('resize', this.get_term_size)

    console.log('WSTerminal: addEventListener created')
  },
  mounted () {
    this.init_websocket()

  },

  beforeUnmount () {
    this.terminalSocket.close();
    this.term.dispose();
  },



  methods: {

   init_websocket(){
    
    // 获取当前窗口大小
    this.cols = this.get_term_size().cols;
    this.rows = this.get_term_size().rows;
    console.log("获取当前窗口大小:",this.cols,this.rows)

    this.loadingText = "创建terminal完毕,开始连接websocket,请等待......"; this.loadingText = "创建terminal完毕,开始连接websocket,请等待......";
    let terminalContainer = document.getElementById("terminal");

    this.term = new Terminal({
      rendererType: "canvas", // 渲染类型
      rows: parseInt(this.rows), // 行数
      cols: parseInt(this.cols), // 不指定行数，自动回车后光标从下一行开始
      convertEol: true, // 启用时，光标将设置为下一行的开头
      //   scrollback: 50, //终端中的回滚量
      disableStdin: false, // 是否应禁用输入。
      cursorStyle: "underline", // 光标样式
      screenKeys: true,
      useStyle: true,
      cursorBlink: true, // 光标闪烁
      theme: {
        foreground: "#7e9192", // 字体
        background: "black", // 背景色
        lineHeight: 16,
      },
    });
    this.term.open(terminalContainer);
    console.log('terminalContainer --> new Terminal() --> term.open')

    const protocol = location.protocol === "https:" ? "wss://" : "ws://";
    const BASE_WS = process.env.VUE_APP_BASE_API.split("/")[2]
    const socketURL = protocol + BASE_WS +
      "/webssh/?id=" +
      this.id +
      "&width=" +
      this.cols +
      "&height=" +
      this.rows;
    // const socketURL = protocol + '192.168.3.128:8001' + '/webterminal/?id=' + this.id + '&width=' + this.cols + '&height=' + this.rows
    this.terminalSocket = new WebSocket(socketURL);
    console.log('terminalSocket URL',this.terminalSocket)
    this.terminalSocket.binaryType = "arraybuffer";
    this.terminalSocket.onopen = this.runFakeTerminal;
    this.terminalSocket.onclose = this.closeRealTerminal;
    this.terminalSocket.onerror = this.errorRealTerminal;
    this.term._initialized = true;
    this.term.focus();
   },
    runFakeTerminal () {
      this.loadingText = "socket已连接,开始连接服务器......";
      var message = { status: 0, data: null, token: null, cols: null, rows: null };
      var term = this.term;
      const that = this;
      var ws = this.terminalSocket;
      
      // 解决不显示初始信息的问题
    //   message["data"] = "\n";
    //   ws.send(JSON.stringify(message));

      // 设置监听，读取服务器端发送的数据并写入 web 终端
      this.terminalSocket.addEventListener("message", function (recv) {
        // 判断是字符串类型还是数据流
        if (typeof (recv.data) === 'string') {
          var data = JSON.parse(recv.data);
          var stdout = data.message;
          var status = data.status;
          
          if (status === 0) {
            // 0为websocket 传递数据
            that.loading = false;
            console.log(stdout)
            term.write(stdout);
          } else {
            // resize pty ssh 终端大小
            that.loading = false;
            term.writeln("\x1B[1;3;31m" + stdout + " \x1B[0m");
          }
        } else {
            console.log('数据流')
        //   zsentry.consume(recv.data);
        }
      });

      /*
       * status 为 0 时, 将用户输入的数据通过 websocket 传递给后台, data 为传递的数据, 忽略 cols 和 rows 参数
       * status 为 1 时, resize pty ssh 终端大小, cols 为每行显示的最大字数, rows 为每列显示的最大字数, 忽略 data 参数
       */

      // 向服务器端发送数据
      this.term.onData(function (data) {
        message["status"] = 0;
        message["data"] = data;
        let token = Cookies.get('CMDB-Token'); 
        message["token"] = token;
        
        var send_data = JSON.stringify(message);
        console.log(send_data)
        ws.send(send_data);
        // console.clear();
      });
      // 监听浏览器窗口, 根据浏览器窗口大小修改终端大小
      window.onresize = function () {
        var cols = that.get_term_size().cols;
        var rows = that.get_term_size().rows;
        message["status"] = 1;
        message["cols"] = cols;
        message["rows"] = rows;
        var send_data = JSON.stringify(message);
        ws.send(send_data);
        // console.log(send_data)
        term.resize(cols, rows);
      };
    },
    errorRealTerminal () {
    //   this.loading = false;
    //   this.term.writeln(
    //     "\x1B[1;3;31m socket建立连接失败，请联系管理员 \x1B[0m"
    //   );
      this.init_websocket() // 断开重连
    },
    closeRealTerminal () {
      this.loading = false;
    //   this.term.write("\r\n");
    //   this.term.writeln("\x1B[1;3;31m 连接关闭 \x1B[0m");
    },
    closeConnect () {
      // 关闭websocket连接
      this.terminalSocket.close();
      // 关闭浏览器
      var userAgent = navigator.userAgent;
      if (userAgent.indexOf("Firefox") != -1 || userAgent.indexOf("Chrome") != -1) {
        window.open('', '_self').close()
      }
    },

    // 获取当前窗口大小
    get_term_size () {
        this.fullWidth = document.documentElement.clientWidth
        this.fullHeight = document.documentElement.clientHeight
        console.log('%c%s', 
        'color: red; font-size: 8px;', 
        'Windows resize: ', this.fullWidth,this.fullHeight)

        const init_width = 10;
        const init_height = 22;

        const windows_width = window.screen.width;
        const windows_height = window.screen.height;
        console.log("cols:",Math.floor(windows_width / init_width))
        console.log("rows:",Math.floor(windows_height / init_height))
        return {
            cols: Math.floor(windows_width / init_width),
            rows: Math.floor(windows_height / init_height),
      };
    },





  },
};
</script>

<style scoped></style>
